package com.vcc.boss.controller;


import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.mybatisflex.core.paginate.Page;
import com.vcc.core.annotations.RestPack;
import com.vcc.core.exception.NotFoundException;
import com.vcc.core.exception.ProgramException;
import com.vcc.core.util.RedisCustomizeUtils;
import com.vcc.data.entity.BossRole;
import com.vcc.data.entity.BossRolePermission;
import com.vcc.data.entity.Permission;
import com.vcc.service.boss.request.role.*;
import com.vcc.service.boss.response.permission.PermissionVoBoss;
import com.vcc.service.boss.response.role.BossRoleVoBoss;
import com.vcc.service.service.*;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("bossRole")
public class RoleController {

    @Autowired
    private BossRoleService bossRoleService;
    @Autowired
    private BossRolePermissionService bossRolePermissionService;
    @Autowired
    private PermissionService permissionService;
    @Resource
    private BossUserBossRoleService bossUserBossRoleService;
    @Resource
    private BossUserService bossUserService;

    @Autowired
    private UserService userService;

    @RestPack
    @SaCheckPermission(value = "admin:role:list:view")
    @GetMapping("paging")
    @SaCheckLogin
    public Page<BossRoleVoBoss> paging(
            Integer pageNumber,
            Integer pageSize,
            String name,String code,Boolean hasAllData,Boolean hasParamStatus) {
        Page<BossRole> paging = bossRoleService.paging(
                Page.of(
                        pageNumber == null || pageNumber < 1 ? 1 : pageNumber,
                        pageSize == null || pageSize < 1 ? 20 : pageSize
                ),
                name,
                code,
                hasAllData,
                hasParamStatus
        );

        return paging.map(it -> {
            List<Permission> permissions = permissionService.listByRoleId(it.getId());
            return new BossRoleVoBoss(it, buildPermissionTreeOptimized(permissions.stream().map(permission -> new PermissionVoBoss(permission, 0)).toList()));
        });
    }

    @RestPack
    @SaCheckPermission(value = "admin:role:list:view")
    @GetMapping("listAll")
    @SaCheckLogin
    public List<BossRoleVoBoss> listAll(String name) {
        List<BossRole> list = bossRoleService.listAll(name);
        return list.stream().map(it -> new BossRoleVoBoss(it, List.of())).toList();
    }

    /**
     * 使用Map优化树构建（O(n)复杂度）
     *
     * @param permissionList 权限列表
     * @return 树状结构的权限列表
     */
    public List<PermissionVoBoss> buildPermissionTreeOptimized(List<PermissionVoBoss> permissionList) {
        if (permissionList == null || permissionList.isEmpty()) {
            return new ArrayList<>();
        }

        // 使用Map存储所有节点，key为节点ID，value为节点对象
        Map<Long, PermissionVoBoss> permissionMap = new HashMap<>();
        List<PermissionVoBoss> rootNodes = new ArrayList<>();

        // 第一次遍历：初始化Map并找到根节点
        for (PermissionVoBoss permission : permissionList) {
            permissionMap.put(permission.getId(), permission);

            // 初始化children列表
            if (permission.getChildren() == null) {
                permission.setChildren(new ArrayList<>());
            }
        }

        // 第二次遍历：建立父子关系
        for (PermissionVoBoss permission : permissionList) {
            Long parentId = permission.getParentId();

            if (parentId == null || parentId == 0) {
                // 根节点
                rootNodes.add(permission);
            } else {
                // 找到父节点并添加到children中
                PermissionVoBoss parent = permissionMap.get(parentId);
                if (parent != null) {
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    parent.getChildren().add(permission);
                }
            }
        }

        return rootNodes;
    }

    @RestPack
    @SaCheckPermission(value = "admin:role:list:view")
    @GetMapping("get")
    @SaCheckLogin
    public BossRoleVoBoss get(Long id) {
        BossRole bossRole = bossRoleService.getById(id);
        List<BossRolePermission> bossRolePermissions = bossRolePermissionService.listByBossRoleId(bossRole.getId());
        List<PermissionVoBoss> permissionVos = bossRolePermissions.stream().map(bossRolePermission -> {
            Permission permission = permissionService.getById(bossRolePermission.getPermissionId());
            return new PermissionVoBoss(permission, bossRolePermission.getStatus());
        }).collect(Collectors.toList());
        return new BossRoleVoBoss(bossRole, permissionVos);
    }


    @RestPack
    @SaCheckPermission(value = "admin:role:edit")
    @PostMapping("updatePermission")
    @SaCheckLogin
    public Boolean updatePermission(@RequestBody @Validated BossRoleDto bossRoleDto) {
        BossRole bossRole = bossRoleService.getById(bossRoleDto.getRoleId());
        bossRoleService.updateRole(bossRole.getId(), bossRoleDto.getHasAllData());
        Set<Long> permissions = permissionService.getRelatedPermissionIdsOptimized(bossRoleDto.getPermissions());
//
//        Set<Long> tempList = new HashSet<>();
//        for (Permission permission : permissions) {
//            if (permission.getParentId() == 0L) {
//                tempList.addAll(permissionService.listIdParentId(permission.getId()));
//            } else {
//                tempList.add(permission.getId());
//                tempList.add(permission.getParentId());
//            }
//        }
        bossRolePermissionService.removeByRoleId(bossRole.getId());
        List<BossRolePermission> bossRolePermissions = permissions.stream().map(it -> {
            BossRolePermission bossRolePermission = new BossRolePermission();
            bossRolePermission.setBossRoleId(bossRole.getId());
            bossRolePermission.setPermissionId(it);
            bossRolePermission.setStatus(0);
            return bossRolePermission;
        }).toList();
        bossRolePermissionService.saveBatch(bossRolePermissions);
        RedisCustomizeUtils.removePrefixKey("user_role_permission:");
        return true;
    }


    @RestPack
    @SaCheckPermission(value = "admin:role:create")
    @SaCheckLogin
    @PostMapping("createRole")
    public Boolean createRole(@RequestBody @Validated CreateRoleDto createRoleDto) {
        BossRole bossRole = bossRoleService.createRole(createRoleDto.getRoleCode(), createRoleDto.getRoleName(), createRoleDto.getHasAllData());
        Set<Long> permissions = permissionService.getRelatedPermissionIdsOptimized(createRoleDto.getPermissions());
//        Set<Long> tempList = new HashSet<>();
//        //匹配到createRoleDto.getPermissions()中的权限,如果是一级菜单,则把该一级菜单下的所有子菜单都添加进去，如果是子菜单，则把该子菜单和它的父菜单都添加进去
//        for (Long permission : createRoleDto.getPermissions()) {
//            Optional<Permission> optional = permissions.stream().filter(it -> it.getId().equals(permission)).findAny();
//            if (optional.isPresent()) {
//                Permission p = optional.get();
//                if (p.getParentId() == 0L) {
//                    tempList.addAll(permissionService.listIdParentId(p.getId()));
//                } else {
//                    tempList.add(p.getId());
//                    tempList.add(p.getParentId());
//                }
//            }
//        }

        List<BossRolePermission> bossRolePermissions = permissions.stream().map(it -> {
            BossRolePermission bossRolePermission = new BossRolePermission();
            bossRolePermission.setBossRoleId(bossRole.getId());
            bossRolePermission.setPermissionId(it);
            bossRolePermission.setStatus(0);
            return bossRolePermission;
        }).toList();
        bossRolePermissionService.saveBatch(bossRolePermissions);
        return true;
    }


    @RestPack
    @SaCheckPermission(value = "admin:role:edit")
    @SaCheckLogin
    @PostMapping("updateHasAllData")
    public Boolean updateHasAllData(@RequestBody @Validated UpdateRoleHasAllDataDto bossRoleDto) {
        BossRole bossRole = bossRoleService.getByIdOpt(bossRoleDto.getId())
                .orElseThrow(() -> new NotFoundException("角色不存在"));
        if (bossRole.getHasAllData().equals(bossRoleDto.getHasAllData())) {
            throw new ProgramException("角色的全部数据权限状态未发生变化");
        }
        bossRoleService.updateRole(bossRole.getId(), bossRoleDto.getHasAllData());
        return true;
    }


    @RestPack
    @SaCheckPermission(value = "admin:role:edit")
    @SaCheckLogin
    @PostMapping("updateHasParamStatus")
    public Boolean updateHasParamStatus(@RequestBody @Validated UpdateRoleHasParamDto bossRoleDto) {
        BossRole bossRole = bossRoleService.getByIdOpt(bossRoleDto.getId())
                .orElseThrow(() -> new NotFoundException("角色不存在"));
        if (bossRole.getHasParamStatus().equals(bossRoleDto.getHasParamStatus())) {
            throw new ProgramException("角色的全部数据权限状态未发生变化");
        }
        bossRoleService.updateRoleHasParamStatus(bossRole.getId(), bossRoleDto.getHasParamStatus());
        return true;
    }

}
